-------------------------------------------------------------------------------
-- mem_hierarchy_rtl.vhd
-------------------------------------------------------------------------------
--
-- This file is part of SKUMLI.
-- Copyright (C) 2011 Davide Giuseppe Monaco (black.ralkass@gmail.com)
--
-- SKUMLI is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- SKUMLI is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with SKUMLI.  If not, see <http://www.gnu.org/licenses/>.
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.cache_controller_pack.all;
use work.cache_pack.all;
use work.mux_pack.all;
use work.ram_pack.all;
use work.register_pack.all;
use work.victim_cache_pack.all;
-------------------------------------------------------------------------------
architecture rtl of mem_hierarchy is

  -- MEM HIERARCHY SIGNALS
  --  + RAM
  signal m_rdy           : std_logic;
  signal m_rw            : std_logic;
  signal m_cs            : std_logic;
  signal m_addr          : std_logic_vector(31 downto 0);
  signal m_dout          : std_logic_vector(31 downto 0);
  --  + CACHE
  signal c_rdy           : std_logic;
  signal c_hit           : std_logic;
  signal c_tab           : std_logic_vector(24 downto 0);
  signal c_rw            : std_logic;
  signal c_cs            : std_logic;
  signal c_addr          : std_logic_vector(31 downto 0);
  signal c_set_v         : std_logic;
  signal c_din_src       : std_logic;
  signal c_din           : std_logic_vector(31 downto 0);
  signal c_dout0         : std_logic_vector(31 downto 0);
  signal c_dout1         : std_logic_vector(31 downto 0);
  signal c_dout2         : std_logic_vector(31 downto 0);
  signal c_dout3         : std_logic_vector(31 downto 0);
  signal c_dout          : std_logic_vector(31 downto 0);
  --  + VICTIM CACHE
  signal v_rdy           : std_logic;
  signal v_hit           : std_logic;
  signal v_tab           : std_logic_vector(29 downto 0);
  signal v_rw            : std_logic;
  signal v_cs            : std_logic;
  signal v_addr          : std_logic_vector(31 downto 0);
  signal v_din           : std_logic_vector(31 downto 0);
  signal v_set_v         : std_logic;
  signal v_set_d         : std_logic;
  signal v_dout0         : std_logic_vector(31 downto 0);
  signal v_dout1         : std_logic_vector(31 downto 0);
  signal v_dout2         : std_logic_vector(31 downto 0);
  signal v_dout3         : std_logic_vector(31 downto 0);
  --  + INTERNAL
  signal mux_ch_din_sel  : std_logic_vector(1 downto 0);
  signal mux_ch_dout_sel : std_logic_vector(1 downto 0);
  signal in_buf0_we      : std_logic;
  signal in_buf1_we      : std_logic;
  signal in_buf2_we      : std_logic;
  signal in_buf3_we      : std_logic;
  signal mux_in_buf_sel  : std_logic_vector(1 downto 0);
  signal out_buf0_we     : std_logic;
  signal out_buf1_we     : std_logic;
  signal out_buf2_we     : std_logic;
  signal out_buf3_we     : std_logic;
  signal mux_out_buf_sel : std_logic_vector(1 downto 0);

  signal in_buf0_dout    : std_logic_vector(31 downto 0);
  signal in_buf1_dout    : std_logic_vector(31 downto 0);
  signal in_buf2_dout    : std_logic_vector(31 downto 0);
  signal in_buf3_dout    : std_logic_vector(31 downto 0);

  signal out_buf0_dout   : std_logic_vector(31 downto 0);
  signal out_buf1_dout   : std_logic_vector(31 downto 0);
  signal out_buf2_dout   : std_logic_vector(31 downto 0);
  signal out_buf3_dout   : std_logic_vector(31 downto 0);

  signal mux_out_buf_dout : std_logic_vector(31 downto 0);

  signal none             : std_logic_vector(31 downto 0) := (others => '1');

  signal v_tab_buf_we    : std_logic;
  signal v_tab_dout      : std_logic_vector(29 downto 0);

begin -- mem_hierarchy
-------------------------------------------------------------------------------
  CC : cache_controller
    port map (
      rw,              -- rw
      cs,              -- cs
      rdy,             -- rdy
      addr,            -- addr
      din,             -- din
      dout,            -- dout
      m_rdy,           -- m_rdy
      v_rdy,           -- v_rdy
      v_hit,           -- v_hit
      v_tab,           -- v_tab
      v_tab_dout,      -- v_tab_buf
      c_rdy,           -- c_rdy
      c_hit,           -- c_hit
      c_tab,           -- c_tab
      c_dout,          -- c_dout
      m_rw,            -- m_rw
      m_cs,            -- m_cs
      m_addr,          -- m_addr
      v_rw,            -- v_rw
      v_cs,            -- v_cs
      v_addr,          -- v_addr
      v_set_v,         -- set valid bit
      v_set_d,         -- set dirty bit
      c_rw,            -- c_rw
      c_cs,            -- c_cs
      c_addr,          -- c_addr
      c_set_v,         -- c_set_v
      c_din_src,       -- c_din_src
      mux_ch_din_sel,  -- mux_ch_din_sel
      mux_ch_dout_sel, -- mux_ch_dout_sel
      in_buf0_we,      -- in_buf0_we
      in_buf1_we,      -- in_buf1_we
      in_buf2_we,      -- in_buf2_we
      in_buf3_we,      -- in_buf3_we
      mux_in_buf_sel,  -- mux_in_buf_sel
      v_tab_buf_we,    -- v_tab_buf_we
      out_buf0_we,     -- out_buf0_we
      out_buf1_we,     -- out_buf1_we
      out_buf2_we,     -- out_buf2_we
      out_buf3_we,     -- out_buf3_we
      mux_out_buf_sel  -- mux_out_buf_sel
    );

  MUX_CH_DIN : mux4x1
    port map (
      mux_ch_din_sel,    -- sel
      din,               -- a
      m_dout,            -- b
      mux_out_buf_dout,  -- c
      none,              -- d
      c_din              -- dout
    );
      
  CCH : cache
    port map (
      c_rw,       -- rw
      c_cs,       -- cs
      c_addr,     -- addr
      c_din,      -- din
      c_set_v,    -- set_v
      c_din_src,  -- din_src
      c_rdy,      -- rdy
      c_hit,      -- hit
      c_tab,      -- tout
      c_dout0,    -- dout0
      c_dout1,    -- dout1
      c_dout2,    -- dout2
      c_dout3     -- dout3
    );

  MUX_CH_DOUT : mux4x1
    port map (
      mux_ch_dout_sel, -- sel
      c_dout0,         -- a
      c_dout1,         -- b
      c_dout2,         -- c
      c_dout3,         -- d
      c_dout           -- dout
    );

  IN_BUF0 : reg
    port map (
      clk, rst,
      in_buf0_we,   -- we
      c_dout0,      -- din
      in_buf0_dout  -- dout
    );

  IN_BUF1 : reg
    port map (
      clk, rst,
      in_buf1_we,   -- we
      c_dout1,      -- din
      in_buf1_dout  -- dout
    );

  IN_BUF2 : reg
    port map (
      clk, rst,
      in_buf2_we,   -- we
      c_dout2,      -- din
      in_buf2_dout  -- dout
    );

  IN_BUF3 : reg
    port map (
      clk, rst,
      in_buf3_we,   -- we
      c_dout3,      -- din
      in_buf3_dout  -- dout
    );

  MUX_IN_BUF : mux4x1
    port map (
      mux_in_buf_sel,  -- sel
      in_buf0_dout,    -- a
      in_buf1_dout,    -- b
      in_buf2_dout,    -- c
      in_buf3_dout,    -- d
      v_din            -- dout
    );
  
  VCH : victim_cache
    port map (
      v_rw,          -- rw
      v_cs,          -- cs
      v_addr,        -- addr
      v_din,         -- din
      v_set_v,       -- set_v
      v_set_d,       -- set_d
      v_rdy,         -- rdy
      v_hit,         -- hit
      v_tab,         -- tout
      v_dout0,       -- dout0
      v_dout1,       -- dout1
      v_dout2,       -- dout2
      v_dout3        -- dout3
    );

  V_TAB_BUF : reg
    generic map ( 30 )
    port map (
      clk, rst,
      v_tab_buf_we,  -- we
      v_tab,         -- din
      v_tab_dout     -- dout
    );

  OUT_BUF0 : reg
    port map (
      clk, rst,
      out_buf0_we,   -- we
      v_dout0,       -- din
      out_buf0_dout  -- dout
    );

  OUT_BUF1 : reg
    port map (
      clk, rst,
      out_buf1_we,   -- we
      v_dout1,       -- din
      out_buf1_dout  -- dout
    );

  OUT_BUF2 : reg
    port map (
      clk, rst,
      out_buf2_we,   -- we
      v_dout2,       -- din
      out_buf2_dout  -- dout
    );

  OUT_BUF3 : reg
    port map (
      clk, rst,
      out_buf3_we,   -- we
      v_dout3,       -- din
      out_buf3_dout  -- dout
    );

  MUX_OUT_BUF : mux4x1
    port map (
      mux_out_buf_sel,  -- sel
      out_buf0_dout,    -- a
      out_buf1_dout,    -- b
      out_buf2_dout,    -- c
      out_buf3_dout,    -- d
      mux_out_buf_dout  -- dout
    );

  MEM : ram
    port map (
      m_rw,              -- rw
      m_cs,              -- cs
      m_addr,            -- addr
      mux_out_buf_dout,  -- din
      m_rdy,             -- rdy
      m_dout             -- dout
    );
  
-------------------------------------------------------------------------------
end rtl;
